﻿/*
 * Created by SharpDevelop.
 * User: Masy Freddy
 * Date: 20/09/2011
 * Time: 17:00
 */
namespace SaverMediaBrowser
{
	using System;
	using System.Collections.Generic;
	using System.Globalization;
	using System.IO;
	using System.Linq;
	using System.Xml.Serialization;

	using MetaVideoEditorEvolved.AddIn.AddInViews;
	using MetaVideoEditorEvolved.AddIn.Entity;
	using MetaVideoEditorEvolved.Helper;

	[System.AddIn.AddIn("MediaBrowser Saver",
	                    Version = "1.0.0.0",
	                    Description = "MediaBrowser Saver",
	                    Publisher = "Masy Freddy")]
	public class MediaBrowser : SaverView
	{
		private const string MovieFileName = "movie.xml",
		SerieFileName = "series.xml",
		OldMovieFileName = "mymovies.xml";
		
		private ConfigurationAddIn configurationAddIn;
		
		public MediaBrowser()
		{
			configurationAddIn = ConfigurationManager.Deserialize();
			
			if(configurationAddIn == null)
			{
				configurationAddIn = new ConfigurationAddIn()
				{
					PathImagesByName = string.Empty,
					TraceLevel = "Error"
				};
				
				ConfigurationManager.Serialize(configurationAddIn);
			}
			
			Tracer.TracerInstance.Level= string.IsNullOrEmpty(configurationAddIn.TraceLevel) ? TracerLevel.Error : (TracerLevel)Enum.Parse(typeof(TracerLevel), configurationAddIn.TraceLevel);
			Tracer.TracerInstance.FileName = "MediaBrowserSaver";
		}
		
		public override void SaveMovie(string mediaLocation, Movie movie)
		{
			try
			{
				Tracer.TracerInstance.TraceInformation(string.Format("Start the SaveMovie in the MediaBrowser Saver in {0}", mediaLocation));
				
				Title title = new Title();

				title.Countries = movie.Countries.ToArray();
				title.RunningTime = movie.Duration.ToString();
				title.Genres = movie.Genres.ToArray();
				title.MPAARating =  movie.MPAARating;
				title.OriginalTitle = movie.OriginalTitle;
				title.Description = movie.Overview;
				title.IMDBrating = movie.Rating.ToString();
				title.Studios = movie.Studios.ToArray();
				title.LocalTitle = movie.Title;
				title.ProductionYear = movie.Year.ToString();
				
				if(movie.CastMembers.Any())
				{
					List<TitlePerson> persons = new List<TitlePerson>();
					
					foreach (var castMember in movie.CastMembers) {
						if(castMember.Picture != null)
						{
							SaveActorImage(castMember.Picture, castMember.FullName);
						}
						
						persons.Add(new TitlePerson()
						            {
						            	Name = castMember.FullName,
						            	Role = castMember.Role,
						            	Type = castMember.Activity
						            });
					}
					
					title.Persons = persons.ToArray();
				}
				
				SaveImage(mediaLocation, movie.Posters, movie.Backdrops, new List<Uri>());
				
				SaveTrailer(mediaLocation, movie.Trailers);
				
				using (StreamWriter sw = new StreamWriter(Path.Combine(mediaLocation, MovieFileName)))
				{
					new XmlSerializer(typeof(Title)).Serialize(sw,title);
				}
				
				Tracer.TracerInstance.TraceSuccessOperation(string.Format("End the SaveMovie in the MediaBrowser Saver in {0}", mediaLocation));
				
				if (this.configurationAddIn.DeleteMyMoviesFile && File.Exists(Path.Combine(mediaLocation, OldMovieFileName))) {
					try
					{
						File.Delete(Path.Combine(mediaLocation, OldMovieFileName));
						Tracer.TracerInstance.TraceSuccessOperation("Old mymovies.xml file deleted");
					}
					catch(Exception ex)
					{
						Tracer.TracerInstance.TraceError("Unable to delete old mymovies.xml file", ex);
					}
				}
			}
			catch(Exception ex)
			{
				Tracer.TracerInstance.TraceError(string.Format("Exception MediaBrowser SaveMovie mediaLocation{0}", mediaLocation), ex);
				throw;
			}
		}
		
		public override void SaveSerie(string mediaLocation, Serie serie)
		{
			try
			{
				Series serieToSave = new Series();
				
				if(serie.CastMembers.Any())
				{
					serieToSave.Actors = "|";
					
					foreach (var castMember in serie.CastMembers) {
						serieToSave.Actors += castMember.FullName;
						serieToSave.Actors += "|";
						
						if(castMember.Picture != null)
						{
							SaveActorImage(castMember.Picture, castMember.FullName);
						}
					}
				}
				
				if(serie.Genres.Any())
				{
					serieToSave.Genre = "|";
					
					foreach (var genre in serie.Genres) {
						serieToSave.Genre += genre;
						serieToSave.Genre += "|";
					}
				}
				
				if(serie.Studios.Any())
				{
					serieToSave.Network = "|";
					
					foreach (var studio in serie.Studios) {
						serieToSave.Network += studio;
						serieToSave.Network += "|";
					}
				}
				
				serieToSave.Rating = decimal.Parse(serie.Rating.ToString(), NumberStyles.Float);
				serieToSave.SeriesName = serie.Name;
				serieToSave.Overview = serie.Overview;
				serieToSave.Runtime = serie.Duration.ToString();
				serieToSave.id = serie.Id;
				
				using (StreamWriter sw = new StreamWriter(Path.Combine(mediaLocation, SerieFileName)))
				{
					new XmlSerializer(typeof(Series)).Serialize(sw, serieToSave);
				}
				
				SaveImage(mediaLocation, serie.Posters, serie.Backdrops, serie.Graphicals);
			}
			catch(Exception ex)
			{
				Tracer.TracerInstance.TraceError(string.Format("Exception MediaBrowser SaveSerie mediaLocation={0}", mediaLocation), ex);
				throw;
			}
		}
		
		public override void SaveSeason(string mediaLocation, Season season)
		{
			try
			{
				if(season.Images.Any())
				{
					var posterPath = season.Images.First().AbsoluteUri;
					
					if(posterPath.Contains("http"))
					{
						var posterImage = DownloadManager.RetrieveImage(posterPath);
						
						if(posterImage != null)
						{
							posterImage.Save(Path.Combine(mediaLocation, "folder.jpg"));
						}
					}
					else
					{
						File.Copy(season.Images.First().LocalPath, Path.Combine(mediaLocation, "folder.jpg"), true);
					}
				}
			}
			catch(Exception ex)
			{
				Tracer.TracerInstance.TraceError(string.Format("Exception MediaBrowser SaveSeason mediaLocation={0}",mediaLocation), ex);
				throw;
			}
		}
		
		public override void SaveEpisode(string mediaLocation, Episode episode)
		{
			try
			{
				FileInfo fi = new FileInfo(mediaLocation);
				string metadataPath = Path.Combine(fi.Directory.FullName, "metadata");
				
				if(!Directory.Exists(metadataPath))
				{
					Directory.CreateDirectory(metadataPath);
				}
				
				Item episodeToSave = new Item()
				{
					EpisodeName = episode.Name,
					EpisodeNumber = episode.Number.ToString(),
					Overview = episode.Overview
				};
				
				if(episode.Directors.Any())
				{
					episodeToSave.Directors = "|";
					
					foreach (var director in episode.Directors) {
						episodeToSave.Directors += director;
						episodeToSave.Directors += "|";
					}
				}
				
				if(episode.GuestStars.Any())
				{
					episodeToSave.GuestStars = "|";
					
					foreach (var gueststar in episode.GuestStars) {
						episodeToSave.GuestStars += gueststar;
						episodeToSave.GuestStars += "|";
					}
				}
				
				if(episode.Writers.Any())
				{
					episodeToSave.Writer = "|";
					
					foreach (var writer in episode.Writers) {
						episodeToSave.Writer += writer;
						episodeToSave.Writer += "|";
					}
				}
				
				episodeToSave.Rating = decimal.Parse(episode.Rating.ToString());
				episodeToSave.SeasonNumber = episode.SeasonNumber.ToString();

				if(episode.Images.Any())
				{
					var posterPath = episode.Images.First().AbsoluteUri;
					
					if(posterPath.Contains("http"))
					{
						var posterImage = DownloadManager.RetrieveImage(posterPath);
						
						if(posterImage != null)
						{
							posterImage.Save(Path.Combine(metadataPath, fi.Name.Replace(fi.Extension, ".jpg")));
						}
					}
					else
					{
						File.Copy(episode.Images.First().LocalPath, Path.Combine(metadataPath, fi.Name.Replace(fi.Extension, ".jpg")), true);
					}
					
					episodeToSave.filename = "/" + fi.Name.Replace(fi.Extension, ".jpg");
				}
				
				using (StreamWriter sw = new StreamWriter(Path.Combine(metadataPath, fi.Name.Replace(fi.Extension,".xml"))))
				{
					new XmlSerializer(typeof(Item)).Serialize(sw, episodeToSave);
				}
			}
			catch(Exception ex)
			{
				Tracer.TracerInstance.TraceError(string.Format("Exception MediaBrowser SaveEpisode mediaLocation={0}", mediaLocation), ex);
				throw;
			}
		}
		
		private void SaveActorImage(Uri path, string name)
		{
			if(!string.IsNullOrEmpty(configurationAddIn.PathImagesByName) &&
			   path != null)
			{
				var pathActorImage =Path.Combine(configurationAddIn.PathImagesByName,"People\\" + name);
				
				if(!Directory.Exists(pathActorImage))
				{
					Directory.CreateDirectory(pathActorImage);
				}
				
				if(path.AbsoluteUri.Contains("http"))
				{
					var posterImage = DownloadManager.RetrieveImage(path.AbsoluteUri);
					
					if(posterImage != null)
					{
						posterImage.Save(pathActorImage + "\\folder.jpg");
					}
				}
				else
				{
					File.Copy(path.LocalPath, pathActorImage + "\\folder.jpg", true);
				}
			}
		}
		
		private void SaveImage(string mediaLocation, List<Uri> poster, List<Uri> backdrops, List<Uri> banner)
		{
			if(configurationAddIn.DeleteImages)
			{
				if(File.Exists(Path.Combine(mediaLocation, "folder.jpg")))
				{
					File.Delete(Path.Combine(mediaLocation, "folder.jpg"));
				}
				
				foreach (var element in new DirectoryInfo(mediaLocation).GetFiles("backdrop*")) {
					File.Delete(element.FullName);
				}
			}
			
			foreach (var posterElement in poster) {
				if(posterElement.AbsoluteUri.Contains("http"))
				{
					var posterImage = DownloadManager.RetrieveImage(posterElement.AbsoluteUri);
					
					if(posterImage != null)
					{
						posterImage.Save(Path.Combine(mediaLocation, "folder.jpg"));
						break;
					}
				}
				else
				{
					File.Copy(posterElement.LocalPath, Path.Combine(mediaLocation, "folder.jpg"), true);
				}
			}

			if(backdrops.Any())
			{
				for (int i = 0; i < backdrops.Count; i++) {
					string nameBackdropFile = i == 0 ? "backdrop.jpg" : string.Format("backdrop{0}.jpg", i);
					if(backdrops[i].AbsoluteUri.Contains("http"))
					{
						var backdropImage = DownloadManager.RetrieveImage(backdrops[i].AbsoluteUri);
						
						if(backdropImage != null)
						{
							backdropImage.Save(Path.Combine(mediaLocation, nameBackdropFile));
						}
					}
					else
					{
						File.Copy(backdrops[i].LocalPath, Path.Combine(mediaLocation, nameBackdropFile), true);
					}
				}
				
				if(banner.Any())
				{
					var bannerPath = banner.First().AbsoluteUri;
					
					if(bannerPath.Contains("http"))
					{
						var bannerImage = DownloadManager.RetrieveImage(bannerPath);
						
						if(bannerImage != null)
						{
							bannerImage.Save(Path.Combine(mediaLocation, "banner.jpg"));
						}
					}
					else
					{
						File.Copy(banner.First().LocalPath, Path.Combine(mediaLocation, "banner.jpg"), true);
					}
				}
			}
		}
		
		public override void ShowOption()
		{
			new Option(configurationAddIn).ShowDialog();
		}
		
		private void SaveTrailer(string mediaLocation, List<Trailer> trailers)
		{
			if(trailers.Any())
			{
				DirectoryInfo di =new DirectoryInfo(mediaLocation);
				var path = Path.Combine(di.FullName, "Trailers");
				
				if(!Directory.Exists(path))
				{
					Directory.CreateDirectory(path);
				}
				
				foreach (var element in trailers) {
					try
					{
						if(element.DefaultPath.AbsoluteUri.Contains("http"))
						{
							//TODO:Decomment the line below when the automatic download is implemented
							//DownloadManager.RetrieveTrailer(element.DefaultPath.AbsoluteUri, Path.Combine(path,Path.GetFileName(element.DefaultPath.LocalPath)));
						}
						else
						{
							if(!File.Exists(Path.Combine(path, Path.GetFileName(element.DefaultPath.LocalPath))))
							{
								File.Copy(element.DefaultPath.LocalPath,Path.Combine(path, Path.GetFileName(element.DefaultPath.LocalPath)), true);
							}
						}
					}
					catch(Exception)
					{
						System.Diagnostics.Debug.WriteLine("The save trailer is interrupted : " + element.DefaultPath.AbsoluteUri + " in location " + mediaLocation);
					}
				}
			}
		}
		
		public override bool HasOption()
		{
			return true;
		}
	}
}